package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"strconv"
)

func main() {
	var port = flag.Int("p", 8080, "监听端口")
	flag.Parse()
	l, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%v", *port))
	if err != nil {
		panic(err)
	}
	defer l.Close()
	defer closePlayer()

	for {
		conn, err := l.Accept()
		if err != nil {
			panic(err)
			break
		}
		log.Println("connection:", conn.RemoteAddr().String())
		playFromConn(conn)
	}
}

func playFromConn(conn net.Conn) {
	defer conn.Close()
	p1, p2 := io.Pipe()
	defer p2.Close()
	defer p1.Close()
	go play(p1)
	buf := make([]byte, 1024)
	var start bool
	var nextIsHead bool
	var remain int
	var end, head, max int
	var noMetaData bool
	buffer := bytes.NewBufferString("")
	for {
		if noMetaData {
			break
		}
		if head > 100000 {
			buffer.Truncate(max - head)
			max -= head
			end -= head
			head = 0
		}
		n, _ := conn.Read(buf)
		if n == 0 {
			break
		}
		buffer.Write(buf[:n])
		data := buffer.Bytes()
		max = len(data)

		for {
			if head >= max {
				break
			}
			end = bytes.Index(data[head:max], []byte("\r\n"))
			v := data[head:max]
			if end >= 0 {
				v = data[head : head+end+2]
			}

			ln1 := bytes.TrimSpace(v)
			if bytes.HasPrefix(ln1, []byte("Icy-MetaData:")) {
				start = false
				nextIsHead = true
				head += len(v)
				continue
			}

			if start {
				//deal 1.get length; 2.read data of length; repeat

				if remain <= 0 {
					ln1 := bytes.TrimSpace(v)
					if len(ln1) == 0 {
						head += len(v)
						continue
					}
					secLen, err := strconv.ParseInt(string(ln1), 16, 32)
					if err != nil {
						head += len(v)
						continue
					}
					//get length
					remain = int(secLen)

					if secLen > 0 {
						//fmt.Printf("section length: %v\n", secLen)
						p2.Write([]byte(fmt.Sprintf("SectionLength:%v\r\n", secLen)))
					} else {
						noMetaData = true
					}

				} else {
					if len(v) <= remain {
						p2.Write(v)
						remain -= len(v)

					} else {
						p2.Write(v[:remain])
						remain = 0
						head += remain
					}
				}
			} else if nextIsHead {
				if remain <= 0 {
					ln1 := bytes.TrimSpace(v)
					if len(ln1) == 0 {
						head += len(v)
						continue
					}
					secLen, err := strconv.ParseInt(string(ln1), 16, 32)
					if err != nil {
						head += len(v)
						continue
					}
					//get length
					remain = int(secLen)
					//fmt.Printf("section length: %v\n", secLen)
					p2.Write([]byte(fmt.Sprintf("Icy-MetaData-Length:%v\r\n", secLen)))
				} else {
					if len(v) < remain {
						p2.Write(v)
						remain -= len(v)

					} else {
						p2.Write(v[:remain])
						remain = 0
						head += remain
						nextIsHead = false
						start = true
						continue
					}
				}

			}
			head += len(v)

		}

	}
	p2.Write([]byte("\r\n"))

	log.Println("finish play")
}
